package rc.database.GetSuperior;

import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import rc.database.connection.MyDBOperations;

import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Slejus
 * Date: 13.11.11
 * Time: 13.43
 * To change this template use File | Settings | File Templates.
 */
public class GetSuperiorIdWebScript extends AbstractWebScript{

    private static final Logger logger = Logger.getLogger(GetSuperiorIdWebScript.class);

    static final String NAMESPACE = "http://*.kada.lt/model/people/1.0";
    static final QName PROP_VAR_ID = QName.createQName(NAMESPACE, "personVarId");

    private PersonService personService;
    private NodeService nodeService;
    private AuthorityService authorityService;


    public void setAuthorityService(AuthorityService authorityService) {
        this.authorityService = authorityService;
    }

    public void setPersonService(PersonService personService) {
        this.personService = personService;
    }

    public void setNodeService(NodeService nodeService) {
        this.nodeService = nodeService;
    }

    @Override
    public void execute(WebScriptRequest webScriptRequest, WebScriptResponse webScriptResponse) throws IOException {
        //ApplicationContext context = new ClassPathXmlApplicationContext("classpath:alfresco/extension/connection-context.xml");
        //DBOperations db = (DBOperations)context.getBean("dbOperations"); // DB operations object
        List<AlfUserData> altUsers = new ArrayList<AlfUserData>();
        List<AlfUserData> alfUsers = new ArrayList<AlfUserData>();
        AlfUserData superior = new AlfUserData();
        List<AlfUserData> altUsersId;
        int vad_id = 0;
        int var_id = 0;

        String username = org.alfresco.repo.security.authentication.AuthenticationUtil.getFullyAuthenticatedUser();
        logger.debug("getFullyAuthenticatedUser: " + username);

        if(personService != null && nodeService != null) {
            String usrGroup = webScriptRequest.getParameter("group");
            logger.debug("Group parameter: " + usrGroup);

            NodeRef personNode = personService.getPerson(username);
            logPersonData(personNode);

            String var_id_str = nodeService.getProperty(personNode, PROP_VAR_ID).toString();
            var_id = Integer.parseInt(var_id_str);

            try {
                //vad_id = getSuperiorId(var_id);
                superior = getSuperiorId(var_id);

                if(vad_id > 0) {
                    //superior = getSuperiorAlfData(vad_id);
                    superior = getSuperiorAlfData(superior);
                }

                altUsersId = getListOfAlternativeUsers(var_id);

                if (altUsersId != null && !altUsersId.isEmpty()) {
                    altUsers = getAlternativeUsersAlfData(altUsersId);
                }

                if (usrGroup != null && !usrGroup.isEmpty()) {
                    alfUsers = getUsersOfAlfrescoGroup("GROUP_" + usrGroup);
                }

                if (altUsers != null && !altUsers.isEmpty()) {
                    for (AlfUserData usr : altUsers){
                        boolean isDuplicate = false;
                        for (AlfUserData alfUser : alfUsers) {
                            if (usr.getAlfUserRef().equals(alfUser.getAlfUserRef())) {
                                isDuplicate = true;
                                logger.debug("DUPLICATE USER: " + usr.getAlfFirstName() + " " + usr.getAlfLastName() + " " + usr.getAlfLastName() );
                                break;
                            }
                        }
                        if (!isDuplicate) {
                            alfUsers.add(usr);
                            logger.debug("ADDED TO ALF USER: " + usr.getAlfFirstName() + " " + usr.getAlfLastName() + " " + usr.getAlfLastName() );
                        }
                    }
                }

                if (alfUsers != null && !alfUsers.isEmpty()) {
                    putToResponse(webScriptResponse, createJsonDataObj(superior, alfUsers));
                } else {
                    badResponse(webScriptResponse);
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            logger.debug("person service or service registry is null");
        }
    }

    private List<AlfUserData> getListOfAlternativeUsers(int var_id)
    {
        //List<String> usersId = new ArrayList<String>();
        List<AlfUserData> users = new ArrayList<AlfUserData>();
        ResultSet rs = null; Connection conn = null; Statement stmt = null;

        if (var_id > 0)
        {
            try
            {
                MyDBOperations db = new MyDBOperations("jussle","E4fc6b54","jdbc:oracle:thin:@kadadev.kada.lan:1521/kadadev","oracle.jdbc.OracleDriver");
                Class.forName(db.getJdbcDriver());
                conn = DriverManager.getConnection(db.getJdbcUrl(), db.getUserName(), db.getPassword());
                conn.setAutoCommit(false);
                stmt = conn.createStatement();
                rs = stmt.executeQuery(db.getAlternativeUsers(var_id));
                users = RsToAlfUsersList(rs,users);
                //usersId = db.RsIntToList(rs);
            }
            catch (ClassNotFoundException ex) {logger.debug(ex);}
            catch (SQLException ex) {logger.debug(ex);}
            finally
            {
                if (rs != null)
                {
                    try {rs.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
                if (stmt != null)
                {
                    try {stmt.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
                if (conn != null)
                {
                    try {conn.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
            }
        }
        logger.debug(users);
        return users;
    }
    
    private List<AlfUserData> getUsersOfAlfrescoGroup(String group){
        List<AlfUserData> usersList = new ArrayList<AlfUserData>();
        logger.debug("Alfresco Group: " + group);
        Set<String> groupUsers = authorityService.getContainedAuthorities(AuthorityType.USER, group, false);
        int groupSize = groupUsers.size();
        logger.debug("Alfresco group size: " + groupSize);
        if (groupSize > 0) {
            for (String authority : groupUsers) {
                NodeRef person = personService.getPerson(authority);
                String name = nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME).toString();
                String surname = nodeService.getProperty(person, ContentModel.PROP_LASTNAME).toString();
                String noderef = person.toString();
                logger.debug("Alfresco user: " + name + " " + surname + " " + noderef);
                usersList.add(new AlfUserData(name, surname, noderef));
            }
        }
        return usersList;
    }

    private AlfUserData getSuperiorId(int var_id)
    {
        ResultSet rs = null; Connection conn = null; Statement stmt = null;
        AlfUserData headCheaf = new AlfUserData();
        int vad_id = 0;

        if (var_id > 0)
        {
            try
            {
                MyDBOperations db = new MyDBOperations("jussle","E4fc6b54","jdbc:oracle:thin:@kadadev.kada.lan:1521/kadadev","oracle.jdbc.OracleDriver");
                Class.forName(db.getJdbcDriver());
                conn = DriverManager.getConnection(db.getJdbcUrl(), db.getUserName(), db.getPassword());
                conn.setAutoCommit(false);
                stmt = conn.createStatement();
                rs = stmt.executeQuery(db.getSuperior(var_id));
                if (rs.next())
                {
                    headCheaf.setAlfUserId(rs.getInt(1));
                    headCheaf.setAlfFirstName(rs.getString(2));
                    headCheaf.setAlfLastName(rs.getString(3));
                    vad_id = rs.getInt(1);
                    logger.debug("(Object) ALF USER DATA: " + headCheaf.getAlfUserId() + " " + headCheaf.getAlfFirstName() + " " + headCheaf.getAlfLastName());

                }
                logger.debug("vadovo_id: " + vad_id);
            }
            catch (ClassNotFoundException ex) {logger.debug(ex);}
            catch (SQLException ex) {logger.debug(ex);}
            finally
            {
                if (rs != null)
                {
                    try {rs.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
                if (stmt != null)
                {
                    try {stmt.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
                if (conn != null)
                {
                    try {conn.close();}
                    catch (SQLException e) {logger.debug(e);}
                }
            }
        }
        //if (vad_id > 0) return vad_id;
        //else return 0;
        return headCheaf;
    }

    private AlfUserData getSuperiorAlfData(AlfUserData superior/*int vad_id*/) throws IOException, JSONException
    {
        //AlfUserData superiorData = new AlfUserData();
        String vartotojoId;
        Set<NodeRef> allUsers =  personService.getAllPeople();
        if (allUsers.size() > 0)
        {
            for (NodeRef personRef : allUsers)
            {
                    if (nodeService.getProperty(personRef, PROP_VAR_ID) != null) {
                        vartotojoId = nodeService.getProperty(personRef, PROP_VAR_ID).toString();
                        int userId = Integer.parseInt(vartotojoId);
                        logger.debug("userId = " + userId + "  vad_id = " + superior.getAlfUserId());
                        if (userId == superior.getAlfUserId())
                        {
                            //superior.setAlfFirstName(nodeService.getProperty(personRef, ContentModel.PROP_FIRSTNAME).toString());
                            //superior.setAlfLastName(nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME).toString());
                            superior.setAlfUserRef(personRef.toString());
                            logger.debug("VIRSININKAS: " + superior.getAlfUserId()+ " " + superior.getAlfFirstName()+ " " + superior.getAlfLastName()+ " " + superior.getAlfUserRef());
                            break;
                        }
                    }
            }
        } else logger.debug("No users founded");
        return superior;
    }

    private List<AlfUserData> getAlternativeUsersAlfData(List<AlfUserData> usersIds)
    {
        //int counter = 0;
        //int listLength = usersIds.size();
        //logger.debug("AltUsers ids size: " + listLength);
        List <AlfUserData> users = new ArrayList<AlfUserData>();
        Set<NodeRef> allUsers =  personService.getAllPeople();
        if (allUsers != null && !allUsers.isEmpty())
        {
            logger.debug("allUsers size: " + allUsers.size());
            for (NodeRef personRef : allUsers)
            {
                if (nodeService.getProperty(personRef, PROP_VAR_ID) != null) {
                    logger.debug("VAR_ID: " + nodeService.getProperty(personRef, PROP_VAR_ID));
                    String vartid = (nodeService.getProperty(personRef, PROP_VAR_ID)).toString();
                    if (vartid != null && !vartid.isEmpty()) {
                        for(AlfUserData usr : usersIds) {
                            int usrId = usr.getAlfUserId();
                            if (usrId == Integer.parseInt(vartid)) {
                                //counter++;
                                logger.debug("Founded var_id match: " + vartid);
                                //String name = nodeService.getProperty(personRef, ContentModel.PROP_FIRSTNAME).toString();
                                //String surname = nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME).toString();
                                String noderef = personRef.toString();
                                users.add(new AlfUserData(usr.getAlfFirstName(), usr.getAlfLastName(), noderef, usr.getAlfUserId()));
                                logger.debug("Alternative db user: "+ usr.getAlfUserId()+ " " + usr.getAlfFirstName() + " " + usr.getAlfLastName() + " " + noderef);
                                break;
                            }
                        }
                    }
                }
            }
        } else logger.debug("No users founded");
        return users;
    }

    private JSONArray createJsonDataObj(AlfUserData superior, List<AlfUserData> altUsers) throws JSONException
    {
        List<JSONObject> objArr = new ArrayList<JSONObject>();
        JSONArray arr = new JSONArray();


        if (superior.getAlfUserRef() != null && (superior.getAlfFirstName() != null || superior.getAlfLastName() != null))
        {
            objArr.add(new JSONObject().put("isDefault","true").put("firstName",superior.getAlfFirstName()).put("lastName", superior.getAlfLastName()).put("userId",superior.getAlfUserRef()));
        } else {
            logger.debug("Superior not found");
        }

        if (!altUsers.isEmpty() && altUsers != null) {
            int listSize = altUsers.size();
            logger.debug("altUsers list size: " + listSize);
            for (int i = 0; i < listSize; i++)
            {
                if (!altUsers.get(i).getAlfUserRef().equals(superior.getAlfUserRef())) {
                    objArr.add(new JSONObject().put("isDefault","false").put("firstName",altUsers.get(i).getAlfFirstName()).put("lastName", altUsers.get(i).getAlfLastName()).put("userId",altUsers.get(i).getAlfUserRef()));
                    logger.debug("Alternative user: " + objArr.get(i));
                }
            }
        }
        int objSize = objArr.size();
        for (int j = 0; j < objSize; j++) {
            arr.put(objArr.get(j));
        }

        logger.debug("User to select:"  + arr);
        return arr;
    }

    private void logPersonData(NodeRef personNode)
    {
        logger.debug("PERSON nodeRef: " + personNode);
        logger.debug("FIRST NAME: " + nodeService.getProperty(personNode, ContentModel.PROP_FIRSTNAME));
        logger.debug("LASTNAME: " + nodeService.getProperty(personNode, ContentModel.PROP_LASTNAME));
        logger.debug("PERSON VAR_ID: " + nodeService.getProperty(personNode, PROP_VAR_ID));
    }

    private void badResponse(WebScriptResponse webScriptResponse) throws JSONException, IOException
    {
        JSONObject object = new JSONObject();
        object.put("members", "none");
        String jsonString = object.toString();
        logger.debug(jsonString);
        webScriptResponse.setContentType("application/json; charset=utf-8");
        webScriptResponse.getWriter().write(jsonString);
    }

    private void putToResponse(WebScriptResponse webScriptResponse, JSONArray arr) throws JSONException, IOException
    {
        if (arr != null) {
            JSONObject object = new JSONObject();
            object.put("members", arr);
            String jsonString = object.toString();
            logger.debug(jsonString);
            webScriptResponse.setContentType("application/json; charset=utf-8");
            webScriptResponse.getWriter().write(jsonString);
        } else {
            logger.debug("JSONArray is null");
            badResponse(webScriptResponse);
        }
    }

    private List<AlfUserData> RsToAlfUsersList(ResultSet rs, List<AlfUserData> list) {
        AlfUserData tmpData = new AlfUserData();
        try {
            while (rs.next()) {
                tmpData.setAlfUserId(rs.getInt(1));
                tmpData.setAlfFirstName(rs.getString(2));
                tmpData.setAlfLastName(rs.getString(3));
                list.add(tmpData);
                logger.debug("RS To ALF USERS: " + list);
                //list.add(Integer.toString(rs.getInt(1)));
            }
        } catch (SQLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return list;
    }
}

class AlfUserData
{

    private String alfFirstName;
    private String alfLastName;
    private String alfUserRef;
    private int alfUserId;

    public AlfUserData(String fName, String lName, String ref, int alfUserId)
    {
        this.alfFirstName = fName;
        this.alfLastName = lName;
        this.alfUserRef = ref;
        this.alfUserId = alfUserId;
    }

    public AlfUserData(String fName, String lName, String ref)
    {
        this.alfFirstName = fName;
        this.alfLastName = lName;
        this.alfUserRef = ref;
    }
    public AlfUserData(){}
    
    public String getAlfFirstName()
    {
        return this.alfFirstName;
    }

    public String getAlfLastName()
    {
        return this.alfLastName;
    }

    public String getAlfUserRef()
    {
        return this.alfUserRef;
    }
    
    public int getAlfUserId()
    {
        return this.alfUserId;
    }
    
    public void setAlfFirstName(String alfFirstNamel)
    {
        this.alfFirstName = alfFirstNamel;
    }
    
    public void setAlfLastName(String alfLastNamel)
    {
        this.alfLastName = alfLastNamel;
    }
    
    public void setAlfUserRef(String alfUserRefl)
    {
        this.alfUserRef = alfUserRefl;
    }
    
    public void setAlfUserId(int alfUserId1)
    {
        this.alfUserId = alfUserId1;
    }

    public Boolean isEmpty()
    {
        if (this.alfUserRef.isEmpty() || this.alfUserRef == null) {
            return true;
        } else return false;
    }

}
